/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/** 
 * \file
 * \brief Very simple testobject for FSRSim
 * \author Antti Maula <antti.maula@tkk.fi>
 */

#include <libxml/parser.h>
#include <libxml/tree.h>
#include "LandMine.h"
#include "World.h"
#include <assert.h>
#include "owndebug.h"


//*****************************************************************************

CObject* CLandMine::LoadMLMA(CWorld *aWorld, xmlNode *aNode)
{
  CObject *object = NULL;

  assert(aWorld != NULL);
  assert(aNode != NULL);


  // Parameters for position
  xmlChar *x = xmlGetProp(aNode, (xmlChar *) "x");
  xmlChar *y = xmlGetProp(aNode, (xmlChar *) "y");
  xmlChar *z = xmlGetProp(aNode, (xmlChar *) "z");
  xmlChar *radius = xmlGetProp(aNode, (xmlChar *) "radius");

  // Process.
  if (x && y && z && radius) {
    float fx,fy,fz,fradius;
    fx = atof((const char*)x);
    fy = atof((const char*)y);
    fz = atof((const char*)z);
    fradius = atof((const char*)radius);

    object = new CLandMine(aWorld, fx, fy, fz, fradius);

  } else {
    dPrint(1,"MLMA Parse Error: Not enough parameter for LandMine");

  }

  // Cleanup (Always do this to clean out properties which were found)
  if (x) xmlFree(x);
  if (y) xmlFree(y);
  if (z) xmlFree(z);  
  if (radius) xmlFree(radius);

  
  if (object){
    aWorld->InsertObject(object);
  }
  
  return object;
}
//*****************************************************************************

CLandMine::CLandMine(CWorld *aWorld, 
                     const float position_x, 
                     const float position_y, 
                     const float position_z,
                     const float radius)
  : CObject(aWorld, NULL),
    iMaterialBase(DEFAULT_MATERIAL),
    iMaterialIgniter(DEFAULT_MATERIAL),
    iBaseRadius(radius),
    iBaseHeight(iBaseRadius/80.0),
    iIgniterRadius(iBaseRadius),
    iIgniterHeight(iIgniterRadius/15.0),
    iMineBase(iBaseRadius, iBaseHeight, this, this->SpaceID, 0, &iMaterialBase, false),
    iMineIgniter(iIgniterRadius, iIgniterRadius, iIgniterHeight, this, this->SpaceID, iMineBase.BodyID, &iMaterialIgniter, false),
    iIsHit(false),
    iIsVisible(true)
{
  Parts.push_back(&iMineBase);
  Parts.push_back(&iMineIgniter);
  
  //place primitives // Note that Y = Z and Z = Y!!!
  
  // The "trigger" is positioned above the base.
  dGeomSetOffsetPosition(iMineIgniter.GeomID, 
                         0.0, 0.0, (iBaseHeight/2.0) + (iIgniterHeight/2.0));
  
  // The whole base (now including the Trigger) is positioned
  dBodySetPosition(iMineBase.BodyID, position_x, position_z, -position_y);

  // ... and translated to correct angle (to face trigger up)
  dMatrix3 R;
  dRFromAxisAndAngle(R, 1, 0, 0, DegToRad(-90));
  dBodySetRotation(iMineBase.BodyID, R);
  
  //set some material properties (Colors for components)
  iMaterialBase.look.color[0] = 1.0;
  iMaterialBase.look.color[1] = 1.0;
  iMaterialBase.look.color[2] = 0.0;
  iMaterialIgniter.look.color[0] = 1.0;
  iMaterialIgniter.look.color[1] = 0.0;
  iMaterialIgniter.look.color[2] = 0.0;

  //we want to know when the Igniter hits something, but don't care about the base.
  iMineBase.NotifyCollisions = false;
  iMineIgniter.NotifyCollisions = true;
}
//*****************************************************************************
    
CLandMine::~CLandMine()
{
  
}
//*****************************************************************************

void CLandMine::Activate()
{
}
//*****************************************************************************

void CLandMine::Update(float StepSize)
{
}
//*****************************************************************************
    
void CLandMine::OnCollision(CPrimitive *aPrimitiveA, 
                            int aContactCount, dContact *aContactsPtr,
                            CPrimitive *aPrimitiveB)
{
  assert(aPrimitiveB != NULL);

  // Check: We are not yet HIT, primitive has BodyID (Not a static object) and
  // the object "collided" is not our own base.
  if (!iIsHit && aPrimitiveB->BodyID && aPrimitiveB != &iMineBase) {
    iIsHit = true;
    
    // Give the object good speed bump to throw it
    const float xv = 0.4, yv = 1000.0, zv = 0.5;

    dBodySetLinearVel(aPrimitiveB->BodyID, xv, yv, zv);

    // Disable collisions; as mine is an "once only" object.
    iMineIgniter.NotifyCollisions = false;
  }

}
//*****************************************************************************
    
void CLandMine::Draw()
{
  if (iIsHit && iIsVisible) {
    static float hitMsBegin = SimWorld->GetSimulationTime();
    float left = 0.15 - (SimWorld->GetSimulationTime()-hitMsBegin);
    dPrint(ODTEST,"Draw a HIT! (%f s left)", left);
    if (left < 0.0) {
      iIsVisible = false;

    } else {
      const dReal *P;
      P = dBodyGetPosition(iMineBase.BodyID);

      dReal M[16];
      ODEToOGL(dBodyGetRotation(iMineBase.BodyID), dBodyGetPosition(iMineBase.BodyID), M);
      glPushAttrib(GL_COLOR_BUFFER_BIT);
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();
      glMultMatrixf(M);
      glColor3f(1.0, 1.0, 1.0);
      drawSphere(2.0-(left*13.3333333333), 10, 0.0, 0.0, 0.0);
      glPopMatrix();
      glPopAttrib();
    }

  } else if (iIsVisible) {
    for (ObjectsIter i=Children.begin(); i != Children.end(); ++i){
      (*i)->Draw();
    }
    
    for (PrimitivesIter i=Parts.begin(); i != Parts.end(); ++i) {
      (*i)->Draw();
    }
  } else {
    const dReal *P;
    P = dBodyGetPosition(iMineBase.BodyID);
    
    dReal M[16];
    ODEToOGL(dBodyGetRotation(iMineBase.BodyID), dBodyGetPosition(iMineBase.BodyID), M);
    glPushAttrib(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glMultMatrixf(M);
    glColor3f(0.3, 0.3, 0.3);
    drawCylinder(0.5, 0.001, PRIMITIVE_DETAIL_LEVEL);
    glPopMatrix();
    glPopAttrib();
  }
}
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
//*****************************************************************************
